package com.apes.framework.plugin.esb.api;

import com.apes.framework.plugin.filereader.xml.ApesElement;
import com.apes.framework.util.RopUtil;
import com.apes.framework.util.Tools;
import com.apes.oap.RopContext;
import com.apes.oap.ServiceMethodDefinition;
import com.apes.oap.ServiceMethodHandler;
import com.apes.oap.annotation.HttpAction;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 功能：
 *
 * @authol
 * @create 2019-11-09 13:50
 */
@Component
public class ServiceMethodManager {
    private static final Logger logger = LogManager.getLogger(ServiceMethodManager.class);

    @Value("${apes.debug.enabled:false}")
    private boolean debug;

    private EsbRouter esbRouter;

    public ServiceMethodManager(EsbRouter esbRouter) {
        this.esbRouter = esbRouter;
    }

    public void addServiceMethod(String methodName, String version) {
        String key = EsbRouter.methodWithVersion(methodName, version);
        ApesElement apesElement = esbRouter.getApesElement(methodName, version);
        try {
            ServiceMethodDefinition definition = buildServiceMethodDefinition(apesElement);
            ServiceMethodHandler serviceMethodHandler = new ServiceMethodHandler();
            serviceMethodHandler.setServiceMethodDefinition(definition);
            List<String> ignoreSignFieldNames = new ArrayList<>();
            ignoreSignFieldNames.add("messageFormat");
            ignoreSignFieldNames.add("sign");
            serviceMethodHandler.setIgnoreSignFieldNames(ignoreSignFieldNames);
            serviceMethodHandler.setHandler(esbRouter);
            Method method = getMethod(apesElement, esbRouter);
            serviceMethodHandler.setHandlerMethod(method);
            serviceMethodHandler.setRopRequestImplType(true);
            serviceMethodHandler.setRequestType(SimpleRequest.class);
            RopContext ropContext = Objects.requireNonNull(RopUtil.getServiceRouter()).getRopContext();
            ropContext.addServiceMethod(definition.getMethod(), definition.getVersion(), serviceMethodHandler);
        } catch (Exception e) {
            logger.error("注册服务方法：" + key + " 错误：" + e);
            e.printStackTrace();
        }
    }

    public void removeServiceMethod(String methodName, String version) {
        RopContext ropContext = Objects.requireNonNull(RopUtil.getServiceRouter()).getRopContext();
        ropContext.removeServiceMethod(methodName, version);
    }

    private ServiceMethodDefinition buildServiceMethodDefinition(ApesElement apesElement) {
        ServiceMethodDefinition definition = Tools.map(apesElement.getAttributes(), ServiceMethodDefinition.class);
        definition.setHttpAction(new HttpAction[]{HttpAction.GET, HttpAction.POST});
        if (debug) {
            definition.setIgnoreSign(true);
            definition.setNeedInSession(false);
        }
        return definition;
    }

    private static Method getMethod(ApesElement apesElement, Object handler) {
        try {
            /*默认开启事务**/
            boolean isTransaction = Boolean.valueOf(apesElement.getAttribute("isTransaction"));
            String methodName = isTransaction ? "invoke" : "process";
            return handler.getClass().getMethod(methodName, SimpleRequest.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
